/*
* Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* $Id: ircmodel.cpp 387 2009-05-06 18:26:23Z jpnurmi $
*/

#include "ircmodel.h"
#include "ircmodelitem.h"
#include <ircutil.h>
#include <QtDebug>

IrcModel::IrcModel(QObject* parent)
    : QStandardItemModel(0, 1, parent) // 0 rows, 1 col
{
}

IrcModel::~IrcModel()
{
}

IrcModelItem* IrcModel::addSession(Irc::Session* session, const QString& name)
{
	return topLevelItem(session, name);
}

void IrcModel::removeSession(Irc::Session* session)
{
    delete d.topLevelItems.take(session);
}

void IrcModel::connected(Irc::Session* session)
{
    IrcModelItem* server = topLevelItem(session);
    server->setEnabled(true);
}

void IrcModel::disconnected(Irc::Session* session)
{
    IrcModelItem* server = topLevelItem(session);
    server->setEnabled(false);
}

void IrcModel::nickChanged(Irc::Session* session, const QString& origin, const QString& nick)
{
    QString source = Irc::Util::nickFromTarget(origin);
    IrcModelItem* server = topLevelItem(session);
    IrcModelItem* receiver = server->findChild(source);
	
    if (receiver)
        receiver->setData(nick, IrcModelItem::NameRole);
    for (int i = 0; i < server->rowCount(); ++i)
    {
        IrcModelItem* receiver = server->child(i);
        IrcModelItem* participant = receiver->findChild(source);
        if (participant)
        {
            participant->setData(nick, IrcModelItem::NameRole);
            receiver->sortChildren(0);
        }
    }
}

void IrcModel::quit(Irc::Session* session, const QString& origin, const QString& message)
{
    QString source = Irc::Util::nickFromTarget(origin);
    IrcModelItem* server = topLevelItem(session);
    for (int i = 0; i < server->rowCount(); ++i)
    {
        IrcModelItem* receiver = server->child(i);
        IrcModelItem* participant = receiver->findChild(source);
        if (participant)
            receiver->removeRow(participant->row());
    }
}

void IrcModel::joined(Irc::Session* session, const QString& origin, const QString& channel)
{
    QString source = Irc::Util::nickFromTarget(origin);
    IrcModelItem* server = topLevelItem(session);
    IrcModelItem* receiver = server->childItem(channel);
    IrcModelItem* participant = receiver->childItem(source);
    receiver->sortChildren(0);
    Q_UNUSED(participant);
}

void IrcModel::parted(Irc::Session* session, const QString& origin, const QString& channel, const QString& message, bool me)
{
    QString source = Irc::Util::nickFromTarget(origin);
    IrcModelItem* server = topLevelItem(session);
    for (int i = server->rowCount() - 1; i >= 0; --i)
    {
        IrcModelItem* receiver = server->child(i);
        IrcModelItem* participant = receiver->findChild(source);

        // nick in a channel
        if (participant && !receiver->text().compare(channel, Qt::CaseInsensitive))
            receiver->removeRow(participant->row());

        // the channel itself
        if (me && !receiver->text().compare(channel, Qt::CaseInsensitive))
            server->removeRow(receiver->row());
   }
}

void IrcModel::channelModeChanged(Irc::Session* session, const QString& origin, const QString& channel, const QString& mode, const QString& args)
{
    Q_UNUSED(origin);
    IrcModelItem* server = topLevelItem(session);
    IrcModelItem* receiver = server->findChild(channel);
    if (receiver)
    {
        IrcModelItem* participant = receiver->findChild(args);
        if (participant)
            participant->setMode(mode);
    }
}

void IrcModel::userModeChanged(Irc::Session* session, const QString& origin, const QString& mode)
{
}

void IrcModel::topicChanged(Irc::Session* session, const QString& origin, const QString& channel, const QString& topic)
{
}

void IrcModel::kicked(Irc::Session* session, const QString& origin, const QString& channel, const QString& nick, const QString& message)
{
    IrcModelItem* server = topLevelItem(session);
    for (int i = 0; i < server->rowCount(); ++i)
    {
        IrcModelItem* receiver = server->child(i);
        IrcModelItem* participant = receiver->findChild(nick);
        if (participant)
            receiver->removeRow(participant->row());
    }
}

void IrcModel::channelMessageReceived(Irc::Session* session, const QString& origin, const QString& channel, const QString& message, bool current)
{
    Q_UNUSED(origin);
    IrcModelItem* server = topLevelItem(session);
    IrcModelItem* receiver = server->findChild(channel);

	if(receiver && !current) {
		
		//TODO : color/coloration in settings
		QBrush brush = receiver->foreground();
		brush.setColor(Qt::red);
		receiver->setForeground(brush);
	}
}

void IrcModel::privateMessageReceived(Irc::Session* session, const QString& origin, const QString& receiver, const QString& message)
{
}

void IrcModel::noticeReceived(Irc::Session* session, const QString& origin, const QString& receiver, const QString& message)
{
    IrcModelItem* server = topLevelItem(session);
    Q_UNUSED(server);
}

void IrcModel::invited(Irc::Session* session, const QString& origin, const QString& nick, const QString& channel)
{
}

void IrcModel::ctcpRequestReceived(Irc::Session* session, const QString& origin, const QString& message)
{
}

void IrcModel::ctcpReplyReceived(Irc::Session* session, const QString& origin, const QString& message)
{
}

void IrcModel::ctcpActionReceived(Irc::Session* session, const QString& origin, const QString& receiver, const QString& message)
{
}

void IrcModel::unknownMessageReceived(Irc::Session* session, const QString& origin, const QStringList& params)
{
}

void IrcModel::numericMessageReceived(Irc::Session* session, const QString& origin, uint event, const QStringList& params)
{
    switch (event)
    {
        case Irc::Rfc::RPL_WELCOME:
        {
            IrcModelItem* item = topLevelItem(session);
            item->setData(origin);
        }
        break;

        case Irc::Rfc::RPL_NAMREPLY:
        {
            QStringList list = params;
            list.removeAll("=");
            list.removeAll("@");

            IrcModelItem* item = topLevelItem(session)->childItem(list.value(1));
            QStringList nicks = list.value(2).split(" ", QString::SkipEmptyParts);
            foreach (const QString& nick, nicks) {
                IrcModelItem* child = item->childItem(nick);
                child->setData(nick); // assure @/+
            }
            item->sortChildren(0);
        }
        break;

        default:
            break;
    }
}

IrcModelItem* IrcModel::topLevelItem(Irc::Session* session, const QString& name)
{
    if (!d.topLevelItems.contains(session))
    {
        IrcModelItem* item = new IrcModelItem(session);
        item->setData(name);
        item->setEnabled(false);
        d.topLevelItems.insert(session, item);
        const_cast<IrcModel*>(this)->appendRow(item);
    }
    return d.topLevelItems.value(session);
}
